package controllers

import (
	"sort"
	"strings"

	"github.com/astaxie/beego"
	"gopkg.in/mgo.v2/bson"
)

type BaseController struct {
	beego.Controller
	Rec *Recv
}

type OnlineController struct {
	BaseController
	User *Loginuser
}

var AppKey string = ""
var Version string = "1.0"

func GetSid() string {
	return ps("%x", string(bson.NewObjectId()))
}

// 检测参数是否注入脚本
func CheckParaLegal(str string) (bres bool) {
	tstr := strings.ToUpper(str)
	if strings.Contains(tstr, "SCRIPT") || strings.Contains(tstr, "SELECT") || strings.Contains(tstr, "UPDATE") || strings.Contains(tstr, "DELETE") ||
		strings.Contains(tstr, "UPDATE") || strings.Contains(tstr, "DROP") || strings.Contains(tstr, "TRUNCATE") {
		bres = false
	}
	bres = true

	return
}

func (this *BaseController) Prepare() {
	//log("RemoteAddr:%v", this.Ctx.Request.RemoteAddr)
	var keys []string
	keys = make([]string, len(this.Ctx.Request.Form))
	idx := 0
	for key, _ := range this.Ctx.Request.Form {
		keys[idx] = key
		idx += 1
	}

	// 按字典顺序排序并构造签名字符窜
	var clisign, strpara string
	sort.Strings(keys)
	for _, val := range keys {
		if val != "sign" {
			strpara += ps("%s=%s&", val, this.Ctx.Input.Query(val))
		} else {
			clisign = this.Ctx.Input.Query(val)
		}
	}
	if len(strpara) > 0 {
		strpara = strpara[0 : len(strpara)-1]
		if !CheckParaLegal(strpara) {
			this.Rec = &Recv{5, "参数不合法", "no data"}
			goto EXIT_BASEPREPARE
		}
	}

	if this.Ctx.Input.URL() == "" {
		// 参数声明
		var (
			sign string
			ver  string
		)

		// 检测必传参数
		if _, ok := this.Ctx.Request.Form["ver"]; !ok {
			this.Rec = &Recv{5, "签名错误1", "no data"}
			goto EXIT_BASEPREPARE
		}

		if _, ok := this.Ctx.Request.Form["ts"]; !ok {
			this.Rec = &Recv{5, "签名错误2", "no data"}
			goto EXIT_BASEPREPARE
		} else {
			// strts := this.Ctx.Input.Query("ts")
			// ts, _ := strconv.Atoi(strts)
			// if ts-10*60 > int(TimeNow) || ts+10*60 < int(TimeNow) {
			// 	log("client:%v svr:%v", ts, TimeNow)
			// 	this.Rec = &Recv{5, "签名错误3", "no data"}
			// 	goto EXIT_BASEPREPARE
			// }
		}

		// 判断版本是否正确
		ver = this.Ctx.Input.Query("ver")
		if ver != Version {
			this.Rec = &Recv{5, "签名错误4", "no data"}
			goto EXIT_BASEPREPARE
		}

		// md5签名
		sign = StrToMD5(strpara + "&key=" + AppKey)
		if sign != clisign {
			log("[%s] server:[%s]  client:[%s]", strpara+"&key="+AppKey, sign, clisign)
			this.Rec = &Recv{5, "签名错误5", "no data"}
		}
	}

EXIT_BASEPREPARE:
	if this.Rec != nil {
		this.Data["json"] = this.Rec
		this.ServeJSON()
	}
	return
}

func (this *BaseController) MoniSrv() {
	this.Rec = &Recv{3, "success", nil}
	return
}

// 请求预处理
func (this *OnlineController) Prepare() {
	// 参数声明
	var (
		sign, clisign, strpara, ver string
		sid                         string
		ok                          bool
	)
	var keys []string
	keys = make([]string, len(this.Ctx.Request.Form))
	idx := 0
	for key, _ := range this.Ctx.Request.Form {
		keys[idx] = key
		idx += 1
	}

	// 按字典顺序排序并构造签名字符窜
	sort.Strings(keys)
	for _, val := range keys {
		if val != "sign" {
			strpara += ps("%s=%s&", val, this.Ctx.Input.Query(val))
		} else {
			clisign = this.Ctx.Input.Query(val)
		}
	}
	if len(strpara) > 0 {
		strpara = strpara[0 : len(strpara)-1]
		if !CheckParaLegal(strpara) {
			this.Rec = &Recv{5, "参数不合法", "no data"}
			goto EXIT_ONLINEPREPARE
		}
	}

	if clisign != "" {
		// 检测必传参数
		if _, ok := this.Ctx.Request.Form["ver"]; !ok {
			this.Rec = &Recv{5, "签名错误1", "no data"}
			goto EXIT_ONLINEPREPARE
		}

		if _, ok := this.Ctx.Request.Form["ts"]; !ok {
			this.Rec = &Recv{5, "签名错误2", "no data"}
			goto EXIT_ONLINEPREPARE
		} else {
			// strts := this.Ctx.Input.Query("ts")
			// ts, _ := strconv.Atoi(strts)
			// if ts-10*60 > int(TimeNow) || ts+10*60 < int(TimeNow) {
			// 	log("client:%v svr:%v", ts, TimeNow)
			// 	this.Rec = &Recv{5, "签名错误:请校准本地时间", "no data"}
			// 	goto EXIT_ONLINEPREPARE
			// }
		}

		// 判断版本是否正确
		ver = this.Ctx.Input.Query("ver")
		if ver != Version {
			this.Rec = &Recv{5, "签名错误3", "no data"}
			goto EXIT_ONLINEPREPARE
		}

		// md5签名
		sign = StrToMD5(strpara + "&key=" + AppKey)
		if sign != clisign {
			log("[%s] server:[%s]  client:[%s]", strpara+"&key="+AppKey, sign, clisign)
			this.Rec = &Recv{5, "签名错误", "no data"}
			goto EXIT_ONLINEPREPARE
		}
	}

	sid = this.GetString("sid")
	if sid == "" {
		this.Rec = &Recv{6, "sid不能为空", "no data"}
	} else if this.User, ok = UserSessions.QueryloginS(sid); !ok {
		this.Rec = &Recv{6, "登录状态已过期,请重新登录", "no data"}
	} else {
		if TimeNow-this.User.LastTime > SidLife {
			this.Rec = &Recv{6, "登录超时,请重新登录", "no data"}
		} else {
			this.User.LastTime = TimeNow
		}
	}

EXIT_ONLINEPREPARE:
	if this.Rec != nil {
		this.Data["json"] = this.Rec
		this.ServeJSON()
	}
	return
}

// 给客户端回复数据
func (this *BaseController) Finish() {
	if this.Rec == nil {
		return
	}
	if this.Rec.Code != -1 {
		if this.Rec.Data == nil {
			this.Rec.Data = "no data"
		}
		this.Data["json"] = this.Rec
	} else {
		this.Data["json"] = this.Rec.Data
	}
	if this.Rec.Code != 6 && !strings.Contains(this.Rec.Msg, "签名") {
		this.ServeJSON()
	}
	return
}
